import {
  computed,
  getCurrentInstance, getCurrentScope, nextTick, onMounted, onScopeDispose, ref, unref
} from 'vue';

// --
export const noop = () => {
};
// --
export const isString = (val) => typeof val === 'string';
// --
export const isDef = (val) => typeof val !== 'undefined';
// --
export const isFunction = (val) => typeof val === 'function';

// --
/**
 * unref: val = isRef(val) ? val.value : val == 是ref对象返回.value 否则返回自身
 */
export function resolveUnref(r) {
  return typeof r === 'function' ? r() : unref(r);
}

// --
/**
 * 返回 vue实例$el对象 无则返回resolveUnref后的值
 * @param elRef
 */
export function unrefElement(elRef) {
  const plain = resolveUnref(elRef);
  const v = plain == null ? undefined : plain.$el;
  return v != null ? v : plain;
}

// 当前effect 作用域销毁时 可以理解为 onUnmounted
export function tryOnScopeDispose(fn) {
  // 返回当前活跃的 effect 作用域
  if (getCurrentScope()) {
    onScopeDispose(fn);
    return true;
  }
  return false;
}

// --

/**
 * 在组件周期内则在onMounted中运行
 *
 * @param fn
 * @param sync false则会在nextTick中运行
 */
export function tryOnMounted(fn, sync = true) {
  if (getCurrentInstance()) onMounted(fn);
  else if (sync) fn();
  else nextTick(fn);
}

// --
/**
 * 是否支持 返回一个ref
 * @param callback
 * @param sync
 */
export function useSupported(callback, sync = false) {
  const isSupported = ref();

  function update() {
    isSupported.value = Boolean(callback());
  }

  update();
  tryOnMounted(update, sync);
  return isSupported;
}

// --
/**
 * 将value/ref/getter规范化为' ref '或' computed '
 */
export function resolveRef(r) {
  return typeof r === 'function' ? computed(r) : ref(r);
}

// --
/**
 * 深拷贝
 * @param source
 */
export function cloneFnJSON(source) {
  return JSON.parse(JSON.stringify(source));
}
